/* graphics.c */

#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>

#include "SDL.h"
#include "SDL_image.h"
#include "SDL_gfxPrimitives.h"

#include "graphics.h"
#include "ponyedit.h"
#include "pony.h"
#include "path.h"
#include "selection.h"

SDL_Surface *screen;
SDL_Surface *map_image;
SDL_Surface *pony_image;

void init_video(int w, int h, int depth, int fullscreen)
{
  if (SDL_Init(SDL_INIT_VIDEO) < 0) {
    printf("ERROR: can't init SDL video\n");
    exit(1);
  }

  SDL_WM_SetCaption("PonyEdit", "PonyEdit");
  
  screen = SDL_SetVideoMode(w, h, depth, (fullscreen) ? (SDL_FULLSCREEN|SDL_HWSURFACE) : SDL_SWSURFACE);
  if (! screen) {
    printf("ERROR: can't set video mode\n");
    exit(1);
  }
}

void load_images(const char *bg_image_name)
{
  pony_image = IMG_Load(DIR_EDITOR_DATA "/pony.png");
  if (pony_image == NULL){
    fprintf(stderr, "ERROR: can't load pony image\n");
    exit(1);
  }

  if (! load_map_bg_image(bg_image_name)) {
    fprintf(stderr, "ERROR: can't load map image '%s'\n", bg_image_name);
    exit(1);
  }
}

int load_map_bg_image(const char *name)
{
  char filename[1024];

  snprintf(filename, sizeof(filename), "%s/%s", DIR_BACKGROUNDS, name);
  map_image = IMG_Load(filename);
  if (map_image == NULL)
    return 0;
  return 1;
}

void draw_rectangle(SDL_Surface *surf, int x, int y, int w, int h, unsigned int color)
{
  vlineColor(surf, x,     y, y+h-1, color);
  vlineColor(surf, x+w-1, y, y+h-1, color);

  hlineColor(surf, x, x+w-1, y,     color);
  hlineColor(surf, x, x+w-1, y+h-1, color);
}

static void draw_point(int x, int y, unsigned int color)
{
  filledCircleColor(screen, x, y, 4, color);
}

static void draw_spawn_point(int x, int y, unsigned int color)
{
  filledCircleColor(screen, x, y, 7, color);
}

static void draw_segment(int x1, int y1, int x2, int y2, unsigned int color)
{
  int cx, cy, cx1, cy1, cx2, cy2;
  double a;

  cx = (x1 + 2 * x2) / 3;
  cy = (y1 + 2 * y2) / 3;
  a = atan2(y2 - y1, x2 - x1);

  cx1 = cx + (6. * cos(a + 5.*M_PI/6.) + 0.5);
  cy1 = cy + (6. * sin(a + 5.*M_PI/6.) + 0.5);
  cx2 = cx + (6. * cos(a - 5.*M_PI/6.) + 0.5);
  cy2 = cy + (6. * sin(a - 5.*M_PI/6.) + 0.5);

  lineColor(screen, x1, y1, x2, y2, color);
  filledTrigonColor(screen, cx, cy, cx1, cy1, cx2, cy2, color);
}

static void draw_statue(int x, int y, int r, unsigned int border_color, unsigned int fill_color)
{
  filledCircleColor(screen, x, y, r, fill_color);
  circleColor(screen, x, y, r, border_color);
}

void draw_arena(int pos_x, int pos_y, PATH *path, EFFECTS *eff)
{
  int i;
  SDL_Rect rect = { pos_x, pos_y, 0, 0 };
  int sel_point, sel_seg_point, sel_seg;

  /* draw background */
  SDL_BlitSurface(map_image, NULL, screen, &rect);

  sel_get_point(&sel_point);
  sel_get_segment(&sel_seg_point, &sel_seg);

  /* draw statue */
  draw_statue(pos_x + path->statue.x, pos_y + path->statue.y, path->statue.radius, 0x4444ffff, 0x4444ff40);

  /* draw path segments*/
  for (i = 0; i < path->num_points; i++) {
    int j;
    PATH_POINT *from = path->points + i;
    for (j = 0; j < from->num_segs; j++) {
      PATH_POINT *to = path->points + from->segs[j].dest_point;
      if (sel_seg_point == i && sel_seg == j)
        draw_segment(pos_x + from->x, pos_y + from->y, pos_x + to->x, pos_y + to->y, 0xff0000ff);
      else
        draw_segment(pos_x + from->x, pos_y + from->y, pos_x + to->x, pos_y + to->y, 0xffffffff);
    }
  }

  /* draw path points */
  for (i = 0; i < path->num_points; i++) {
    PATH_POINT *p = path->points + i;

    if (path_is_spawn_point(path, i))
      draw_spawn_point(pos_x + p->x, pos_y + p->y, 0x0000ffff);

    if (sel_point == i)
      draw_point(pos_x + p->x, pos_y + p->y, 0xff0000ff);
    else
      draw_point(pos_x + p->x, pos_y + p->y, 0xffffffff);
  }

  /* draw effects */
  if (eff->shadow_point) {
    if (eff->shadow_point_x1 != eff->shadow_point_x2 || eff->shadow_point_y1 != eff->shadow_point_y2)
      draw_segment(pos_x + eff->shadow_point_x1, pos_y + eff->shadow_point_y1,
		   pos_x + eff->shadow_point_x2, pos_y + eff->shadow_point_y2, 0xaaaaaaff);
    draw_point(pos_x + eff->shadow_point_x2, pos_y + eff->shadow_point_y2, 0xaaaaaaff);
  }
  if (eff->shadow_segment)
    draw_segment(pos_x + eff->shadow_segment_x1, pos_y + eff->shadow_segment_y1,
		 pos_x + eff->shadow_segment_x2, pos_y + eff->shadow_segment_y2, 0xaaaaaaff);

}
